package com.dotflat.utils;

//import com.matt.commons.exception.BusinessException;

import com.starinside.wp.foundation.exception.BusinessException;
import com.starinside.wp.foundation.model.ErrorCode;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;


/**
 * 基于Java8的日期工具类。
 *
 * @author Tim.Yao，sunfuchang03@126.com
 * @version 1.1 添加注释，添加日期加上日期数计算方法
 * @since 1.0
 */
public class DateUtil {
    /**
     * 获取某一段日期的开始时间和结束时间。
     *
     * @param currentDay 日期字符串
     * @param separator  日期字符串的分隔符
     * @return 包含开始日期毫秒数和结束日期毫秒的map，开始key为<value>beg</value>，结束key<value>end</value>
     * @throws Exception
     */
    public static final Map<String, Long> getCurrentDayBeginAndEnd(String currentDay, String separator) throws Exception {
        Long beg = null;
        Long end = null;
        Map<String, Long> timeMap = new HashMap<>();
        if (StringUtils.isNotBlank(currentDay) && StringUtils.isNotBlank(separator)) {
            try {
                String[] dates = currentDay.split(separator);
                beg = parseToMills(dates[0] + " 00:00:00:000");
                end = parseToMills(dates[1] + " 23:59:59:999");
                timeMap.put("beg", beg);
                timeMap.put("end", end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
            return timeMap;
        }
        return null;
    }

    /**
     * 获取某一段日期的开始时间和结束时间。
     *
     * @param currentDay 日期字符串
     * @return 包含开始日期毫秒数和结束日期毫秒的map，开始key为<value>beg</value>，结束key<value>end</value>
     * @throws Exception
     */
    public static final Map<String, Date> getCurrentDayBeginAndEnd(String currentDay) {
        Map<String, Date> timeMap = new HashMap<>();

        try {
            timeMap.put("beg", parseToDateMilis(currentDay + " 00:00:00:000"));
            timeMap.put("end", parseToDateMilis(currentDay + " 23:59:59:999"));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return timeMap;
    }

    /**
     * 获取某一段日期的开始时间和结束时间。
     *
     * @param date 当前日期
     * @return 包含开始日期毫秒数和结束日期毫秒的map，开始key为<value>beg</value>，结束key<value>end</value>
     * @throws Exception
     */
    public static final Map<String, Date> getCurrentDayBeginAndEnd(Date date) {
        Map<String, Date> timeMap = new HashMap<>();
        String currentDay = convertStr(date);
        try {
            timeMap.put("beg", parseToDateMilis(currentDay + " 00:00:00:000"));
            timeMap.put("end", parseToDateMilis(currentDay + " 23:59:59:999"));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return timeMap;
    }

    /**
     * 获得当天的开始时间
     *
     * @param millis
     * @return
     */
    public static final long startOfDayOfMilli(Long millis) {
        return LocalDateTime
                .of(Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDate(), LocalTime.MIDNIGHT)
                .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 获得当天的结束时间
     *
     * @param millis
     * @return
     */
    public static final long endOfDayOfMilli(Long millis) {
        return LocalDateTime
                .of(Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDate(), LocalTime.MAX)
                .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 将字符串日期格式解析为日期毫秒数。
     *
     * @param formatDate 日期字符串
     * @return 日期毫秒数
     * @throws ParseException
     */
    public static final Long parseToMills(String formatDate) throws ParseException {
        Date dt = parseToDate(formatDate);
        return dt.getTime();
    }

    /**
     * 精确的月份
     * @param bigger
     * @param smaller
     * @return
     */
    public static final double betweenMonthsV2(Date bigger, Date smaller) {
        if (bigger.compareTo(smaller) < 0)
            return 0;
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(bigger);
        c2.setTime(smaller);
        Integer year = c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
        int month = c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
        int days = c1.get(Calendar.DAY_OF_MONTH) - c2.get(Calendar.DAY_OF_MONTH);

        double daysOfMonth = getDayCountOfMonth() * 1.0;

        double monthDelta = days * 1.0 / daysOfMonth;

        double ret = month + (year * 12) + monthDelta;

        return ret;
    }

    private static int getDayCountOfMonth(){
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        int day = aCalendar.getActualMaximum(Calendar.DATE);
        return day;
    }


    /**
     * 计算开始日期和结束日期之间相差的月份数。
     *
     * @param bigger
     * @param smaller
     * @return
     * @throws ParseException
     */
    public static final int betweenMonths(String bigger, String smaller) throws ParseException {
        return betweenMonths(parseToDate(bigger), parseToDate(smaller));
    }

    public static final int betweenMonths(Date bigger, Date smaller) {
       double ret = betweenMonthsV2(bigger, smaller);
       return (int) (ret + 0.5);
    }

    public static final int betweenDay(Date bigger, Date smaller) {
        int count=0;
        if (bigger.compareTo(smaller) < 0)
            return 0;
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(bigger);
        c2.setTime(smaller);
        Integer year = c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
        int month = c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
        int days = c1.get(Calendar.DAY_OF_MONTH) - c2.get(Calendar.DAY_OF_MONTH);
        count = year*365 +month*30 +days;
        return count;
    }


    /**
     * 计算开始日期和结束日期之间相差的小时数。
     *
     * @param begin 开始日期字符串
     * @param end   结束日期字符串
     * @return 小时数
     * @throws ParseException
     */
    public static final long betweenHour(String begin, String end) throws ParseException {
        long deltaMillis = parseToDateHour(end).getTime() - parseToDateHour(begin).getTime();
        return Duration.ofMillis(deltaMillis).toHours();
    }

    /**
     * 计算开始日期和结束日期之间相差的小时数。
     *
     * @param begin 开始日期毫秒数
     * @param end   结束日期毫秒数
     * @return 小时数
     * @throws ParseException
     */
    public static final long betweenHour(long begin, long end) {
        long deltaMillis = end - begin;
        return Duration.ofMillis(deltaMillis).toHours();
    }

    /**
     * 将完整日期解析为包含年月日时分的日期，不包括秒。
     *
     * @param formatDate 原始完整日期字符串
     * @return 包含年月日时分的日期，秒为0
     * @throws ParseException
     */
    public static final Date parseToDateHour(String formatDate) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            if (formatDate.contains("年") || formatDate.contains("月") || formatDate.contains("日")) {
                sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            if (formatDate.contains("/")) {
                sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException("800000", "日期格式错误");
        }
    }

    /**
     * 将字符串日期格式化为日期对象。
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToDateMilis(String formatDate) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (formatDate.contains("年") || formatDate.contains("月") || formatDate.contains("日")) {
                sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            if (formatDate.contains("/")) {
                sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException("800000", "日期格式错误");
        }
    }

    /**
     * 将字符串日期格式化为包含年月日的日期，时分秒为0.
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToDate(String formatDate) {

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            if (formatDate.contains("年") || formatDate.contains("月") || formatDate.contains("日")) {
                sdf = new SimpleDateFormat("yyyy年MM月dd日");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            if (formatDate.contains("/")) {
                sdf = new SimpleDateFormat("yyyy/MM/dd");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException("800000", "日期格式错误");
        }
    }

    /**
     * 将字符串日期格式化为包含年月日的日期，时分秒为0.
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToHour(String formatDate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        if (formatDate.contains("时") || formatDate.contains("分")) {
            sdf = new SimpleDateFormat("HH时mm分");
            Date dt = sdf.parse(formatDate);
            return dt;
        }
        if (formatDate.contains("/")) {
            sdf = new SimpleDateFormat("HH/mm");
            Date dt = sdf.parse(formatDate);
            return dt;
        }
        Date dt = sdf.parse(formatDate);
        return dt;
    }

    public static final Date parseToPattern(String formatDate, String pattern) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException("800000", "日期格式错误");
        }
    }

    /**
     * 将字符串日期格式化为包含年月日的日期，时分秒为0.
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToHourMillis(String formatDate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        if (formatDate.contains("时") || formatDate.contains("分") || formatDate.contains("秒")) {
            sdf = new SimpleDateFormat("HH时mm分ss秒");
            Date dt = sdf.parse(formatDate);
            return dt;
        }
        if (formatDate.contains("/")) {
            sdf = new SimpleDateFormat("HH/mm/ss");
            Date dt = sdf.parse(formatDate);
            return dt;
        }
        Date dt = sdf.parse(formatDate);
        return dt;
    }

    /**
     * 获取某一日期是当月的第几天，从1开始。
     *
     * @param instant 日期毫秒数
     * @return 当月第几天
     */
    public static final int getDayOfMonth(long instant) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).getDayOfMonth();
    }

    public static String getBeginOfCurrentMonth(SimpleDateFormat format) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        String first = format.format(c.getTime());
        return first;
    }

    public static Date getBeginOfCurrentMonth() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        return c.getTime();
    }

    public static Date getEndOfCurrentMonth() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        return c.getTime();
    }

    public static String getEndOfCurrentMonth(long instant, SimpleDateFormat format) {
        Calendar ca = Calendar.getInstance();
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        String last = format.format(ca.getTime());
        return last;
    }

    public static final long betweenDays(String begin, String end) throws ParseException {
        long beginTime = parseToMills(begin);
        long endTime = parseToMills(end);
        return countDays(endTime - beginTime);
    }

    public static final long betweenDays(Date begin, Date end) {
        long beginTime = begin.getTime();
        long endTime = end.getTime();
        return countDays(endTime - beginTime);
    }

    public static final long betweetMillis(Date begin, Date end) {
        long beginTime = begin.getTime();
        long endTime = end.getTime();
        return countMillis(endTime - beginTime);
    }

    public static final long countDays(long deltaMillis) {
        return Duration.ofMillis(deltaMillis).toDays();
    }

    public static final long countMillis(long deltaMillis) {
        return Duration.ofMillis(deltaMillis).toMillis();
    }


    public static final long plusMonths(long instant, long months) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).plusMonths(months).toInstant().toEpochMilli();
    }

    public static final long plusDays(long instant, long days) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).plusDays(days).toInstant().toEpochMilli();
    }

    public static final long minusDays(long instant, long days) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).minusDays(days).toInstant().toEpochMilli();
    }

    public static final Long plusDays(String currentDay, long days){
        try{
            long current = parseToMills(currentDay);
            return plusDays(current, days);
        } catch (ParseException e) {
            throw new BusinessException("800000", "日期格式错误");
        }
    }

    public static final Date plusYear(String currentDay, int year) throws ParseException {
        return new Date(plusDays(currentDay, year * 365));
    }

    public static final String plusDaysToString(String currentDay, long day, String pattern) throws ParseException {
        long millis = plusDays(currentDay, day);
        return millisToDateTime(millis, pattern);
    }

    public static final Date plusDaysToDate(String currentDay, long days) throws ParseException {
        long millis = plusDays(currentDay, days);
        return new Date(millis);
    }

    /**
     * 计算日期加上某天数后的日期。
     *
     * @param currentDay 原始日期
     * @param days       天数
     * @return 计算后的日期
     * @throws ParseException
     */
    public static final Date plusDaysToDate(Date currentDay, long days) {
        long millis = plusDays(currentDay.getTime(), days);
        return new Date(millis);
    }

    /**
     * 日期的毫秒数加上秒数，得到的日期毫秒。
     *
     * @param instant 日期的毫秒数
     * @param seconds 描述
     * @return 计算后的日期毫秒数
     */
    public static final long plusSeconds(long instant, long seconds) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).plusSeconds(seconds).toInstant().toEpochMilli();
    }

    /**
     * 日期的毫秒数加上分钟数，得到的日期毫秒。
     *
     * @param instant 日期的毫秒数
     * @param minutes 分钟数
     * @return 计算后的日期毫秒数
     */
    public static final long plusMinutes(long instant, long minutes) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).plusMinutes(minutes).toInstant().toEpochMilli();
    }

    /**
     * 计算日期加上某小时数后的日期。
     *
     * @param srcDate 原始日期
     * @param hours   小时数
     * @return 计算后日期
     */
    public static final Date plusHoursToDate(Date srcDate, int hours) {
        long milli = Instant.ofEpochMilli(srcDate.getTime()).atZone(ZoneId.systemDefault()).plusHours(hours).toInstant().toEpochMilli();
        return new Date(milli);
    }

    public static final String millisToDateTime(Long millis, String pattern) {
        LocalDateTime time = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDateTime();
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static final String getBeginOfTheMouth(long instant) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).with(TemporalAdjusters.firstDayOfMonth()).toString();
    }

    public static final boolean isBeforeThanToday(Date day) throws ParseException {
        long now = System.currentTimeMillis();
        return day.getTime() < now;
    }

    /**
     * 判断某一时间是否在一个区间内
     *
     * @param sourceTime 时间区间,半闭合,如[10:00-20:00)
     * @param curTime    需要判断的时间 如10:00
     * @return
     * @throws IllegalArgumentException
     */
    public static boolean isInTime(String sourceTime, String curTime) {
        if (sourceTime == null || !sourceTime.contains("-") || !sourceTime.contains(":")) {
            throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
        }
        if (curTime == null || !curTime.contains(":")) {
            throw new IllegalArgumentException("Illegal Argument arg:" + curTime);
        }
        String[] args = sourceTime.split("-");
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        try {
            long now = sdf.parse(curTime).getTime();
            long start = sdf.parse(args[0]).getTime();
            long end = sdf.parse(args[1]).getTime();
            if (args[1].equals("00:00")) {
                args[1] = "24:00";
            }
            if (end < start) {
                if (now >= end && now < start) {
                    return false;
                } else {
                    return true;
                }
            } else {
                if (now >= start && now < end) {
                    return true;
                } else {
                    return false;
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
        }
    }
    public static Date getLaskWeekDay(String date){
        Long millis = LocalDateTime.ofInstant(Instant.ofEpochMilli(parseToDate(date).getTime()), ZoneId.systemDefault()).toLocalDate().minusDays(7L).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        return new Date(millis);
    }

    public static Date getWeekBegin(Date today) {
        Long intervalDay = Long.valueOf(LocalDate.now().getDayOfWeek().getValue() - DayOfWeek.MONDAY.getValue());
        Long millis = LocalDateTime.ofInstant(Instant.ofEpochMilli(today.getTime()), ZoneId.systemDefault()).toLocalDate().minusDays(intervalDay).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        return new Date(millis);
    }

    public static Date getWeekEnd(Date today) {
        Long intervalDay = Long.valueOf(DayOfWeek.SUNDAY.getValue() - LocalDate.now().getDayOfWeek().getValue());
        Long millis = LocalDateTime.ofInstant(Instant.ofEpochMilli(today.getTime()), ZoneId.systemDefault()).toLocalDate().plusDays(intervalDay).atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        return new Date(millis);
    }

    public static boolean hasTimeUnionSet(Date beg1, Date end1, Date beg2, Date end2){
        if (beg2.compareTo(end1) >= 0 || beg1.compareTo(end2) >= 0)
            return false;
        return true;
    }

    public static boolean isInTime(Date birthday, Integer beginMonth, Integer endMonth){
        int month =betweenMonths(new Date(), birthday);
        return month >= beginMonth && month <= endMonth;
    }

    public static String convertStr(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return  sdf.format(date);
    }

    public static Date parseToDayHourM(String str){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        try {
            Date date = sdf.parse(str);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Illegal Argument arg:" + str);
        }
    }
    
    public static Date parseToDayHourMS(String str){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = sdf.parse(str);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Illegal Argument arg:" + str);
        }
    }

    public static boolean getWorkDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if(cal.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY ||cal.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY)
            return false;
        return true;
    }

    public static boolean isWednesday(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if(cal.get(Calendar.DAY_OF_WEEK)==Calendar.WEDNESDAY)
            return true;
        return false;
    }

    public static boolean isFriday(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if(cal.get(Calendar.DAY_OF_WEEK)==Calendar.FRIDAY)
            return true;
        return false;
    }

    /**
     * 返回 "xx月xx日"格式
     * @param date
     * @return
     */
    public static String dateToMd(Date date){
        SimpleDateFormat sdf=new SimpleDateFormat("MM月dd日");
        return sdf.format(date);
    }

    /**
     * 返回yyyy-MM-dd格式的当天
     * @return
     */
    public  static  String getToday(){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String today  = sdf.format(date);
        return today;
    }

    /**
     * 返回yyyy-MM
     * @return
     */
    public  static  String getMonth(){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        String today  = sdf.format(date);
        return today;
    }
    /**
     * 返回yyyy-MM
     * @return
     */
    public  static  String getReduceMonth(Integer month){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance(); //创建Calendar 的实例
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);//当前时间减去一个月，即一个月前的时间
        String today  = sdf.format(calendar.getTime());
        return today;
    }

    public  static  String getReduceDay(Integer day,Date date){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance(); //创建Calendar 的实例
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, day);//当前时间减去一个月，即一个月前的时间
        String today  = sdf.format(calendar.getTime());
        return today;
    }

    public  static  String getReduceWeek(Integer day,Date date){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance(); //创建Calendar 的实例
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, day*7);//当前时间减去一个月，即一个月前的时间
        Date date1 =  getBeginDayOfWeek(calendar.getTime());
        String today  = sdf.format(date1.getTime());
        return today + " 00:00:00";
    }

    public  static  String getReduceWeekEnd(Integer day,Date date){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance(); //创建Calendar 的实例
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, day*7);//当前时间减去一个月，即一个月前的时间
        Date date1 =  getEndDayOfWeek(calendar.getTime());
        String today  = sdf.format(date1.getTime());
        return today+ " 23:59:59";
    }

    public  static  String getYear(){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        String today  = sdf.format(date);
        return today;
    }

    /**
     * 比较日期 年月日 是否在同一天
     * @param d1
     * @param d2
     * @return
     */
    public static boolean sameDate(Date d1, Date d2){
        return DateUtils.isSameDay(d1, d2);
    }


    /**
     * 判断给定日期是否为月末的一天
     *
     * @param date
     * @return true:是|false:不是
     */
    public static boolean isLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DATE, (calendar.get(Calendar.DATE) + 1));
        if (calendar.get(Calendar.DAY_OF_MONTH) == 1) {
            return true;
        }
        return false;
    }

    //获取下周的开始时间
    public static Date getBeginDayOfNextWeek() {
        Date date = getBeginDayOfWeek();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, 7);
        return cal.getTime();
    }

    public static Date getEndDayOfNextWeek() {
        Date date = getEndDayOfWeek();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, 7);
        return cal.getTime();
    }

    // 获取本周的开始时间
    public static Date getBeginDayOfWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek);
        return cal.getTime();
    }

    // 获取指定周的开始时间
    public static Date getBeginDayOfWeek( Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek);
        return cal.getTime();
    }

    // 获取本周的结束时间
    public static Date getEndDayOfWeek() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return weekEndSta;
    }


    // 获取本周的结束时间
    public static Date getEndDayOfWeek( Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek(date));
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return weekEndSta;
    }
    public  static String formatDayToStr(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dayStr  = sdf.format(date);
        return dayStr;
    }

    public  static String formatDayToStrByMask(Date date,String mask){
        SimpleDateFormat sdf = new SimpleDateFormat(mask);
        String dayStr  = sdf.format(date);
        return dayStr;
    }


    public static String  getWeekStartDay(){
       return formatDayToStr(getBeginDayOfWeek());
    }

    public static String  getWeekEndDay(){
        return formatDayToStr(getEndDayOfWeek());
    }

    /**
     * 获取当前月份
     * @return
     */
    public static int getCurrentMonth(){
        Calendar cal = Calendar.getInstance();
        int month = cal.get(Calendar.MONTH )+1;
        return month ;
    }

    public static boolean isDecember(){
        boolean flag = false;
        int month = getCurrentMonth();
        if(month == 12){
            flag = true;
        }
        return flag;
    }

    /**
     * 当前所属月份的最后一天
     * @return
     */
    public static String getLastDayOfMonth() {
        Calendar cal = Calendar.getInstance();
        int lastDay = cal.getActualMaximum(Calendar.DATE);
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    /**
     * 查询当前时间 是否月末最后7天
     */
    public static boolean getLastWeekOfMonth(){
        boolean flag = true ;
        String today = formatDayToStr(new Date());

        String lastDayOfMonth = getLastDayOfMonth();//月末最后一天时间
        System.out.println("月末最后一天:" + lastDayOfMonth);
        Date ldm = DateUtil.parseToDate(lastDayOfMonth);
        Calendar cal = Calendar.getInstance();
        cal.setTime(ldm);
        cal.add(Calendar.DAY_OF_MONTH, -6);
        String sevenDay = formatDayToStr(cal.getTime());//前推7天
        System.out.println("前推7天:" + sevenDay);

        if(sevenDay.compareTo(today) >0){
            flag = false ;
        }



        return  flag;
    }

    public static final String parseToDateTime(Date date) {
        SimpleDateFormat sdf =  new SimpleDateFormat("yyyy年MM月dd日 HH时mm分");
        String dayStr  = sdf.format(date);
        return dayStr ;

    }

    public static final String parseToDate(Date date) {
        SimpleDateFormat sdf =  new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        String dayStr  = sdf.format(date);
        return dayStr ;

    }

    public static final String parseToDateDay(Date date) {
        SimpleDateFormat sdf =  new SimpleDateFormat("yyyy年MM月dd日");
        String dayStr  = sdf.format(date);
        return dayStr ;

    }

    //获取当前周 所有的日期 周一到周日
    public static String[] getWeekDay() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
            calendar.add(Calendar.DAY_OF_WEEK, -1);
        }
        String [] dates = new String[7];
        for (int i = 0; i < 7; i++) {
            dates[i] = dateFormat.format(calendar.getTime());
            calendar.add(Calendar.DATE, 1);
        }
        return dates;
    }
    
    public static final Date parseLocalDateTimeToDate(String lessonDate,Time hourseTime) {
    	LocalTime mid=hourseTime.toLocalTime();
		LocalDate date = LocalDate.parse(lessonDate);    
    	ZoneId zoneId = ZoneId.systemDefault();  		
        LocalDateTime beginLocalDateTime = LocalDateTime.of(date.getYear(), date.getMonth(), date.getDayOfMonth(), mid.getHour(), mid.getMinute(), mid.getSecond());      		  
        ZonedDateTime zdt = beginLocalDateTime.atZone(zoneId);
        Date dateTime = Date.from(zdt.toInstant());
        return dateTime ;

    }
    
    public  static String formatDateToStr(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dayStr  = sdf.format(date);
        return dayStr;
    }
    public  static String formatDateToHmsStr(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        String hmsStr  = sdf.format(date);
        return hmsStr;
    }
    
    public static Date parseToDay(String str){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = sdf.parse(str);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Illegal Argument arg:" + str);
        }
    }
    public static void main(String[] args) throws Exception {
        Date today = new Date();



//        LocalDate date = LocalDateTime.ofInstant(Instant.ofEpochMilli(today.getTime()), ZoneId.systemDefault()).toLocalDate();
//        System.out.println(DateUtil.betweenMonths("2000-2-29", "2000-1-31"));
//        Date time = DateUtil.parseToDate("2018-08-06 00:05:00");
//        time = DateUtil.plusHoursToDate(time, -1);
//        System.out.println(DateUtil.millisToDateTime(time.getTime(), "yyyy-MM-dd HH:mm:ss"));
//        System.out.println(DateUtil.betweenMonths(DateUtil.parseToDate("2018-10-23"), DateUtil.parseToDate("2016-05-17")));
        //System.out.println(DateUtil.millisToDateTime(getLaskWeekDay("2018-11-26").getTime(), "yyyy-MM-dd"));
        SimpleDateFormat df =new SimpleDateFormat("yyyy-MM-dd");
        Date d1=df.parse("2018-12-01");
        Date d2=df.parse("2018-12-02");
        Date d3=df.parse("2019-04-28");
        System.out.println(parseToDate(today));

      /*  System.out.println(getLastDayOfMonth());
        String lastDayOfMonth = getLastDayOfMonth();
        Date ldm = DateUtil.parseToDate(lastDayOfMonth);
        Calendar cal = Calendar.getInstance();
        cal.setTime(ldm);
        cal.add(Calendar.DAY_OF_MONTH, -6);
        String firstDay = formatDayToStr(cal.getTime());
        System.out.println(firstDay);*/
     //   boolean isendMonth = isLastDayOfMonth(d3);
      //  System.out.println(getWeekStartDay());
     //   System.out.println(getWeekEndDay());
    //    System.out.println(getCurrentMonth());
        //System.out.println(betweenDay(d1,d2));
        //System.out.println(d3.getDay());
     /*   System.out.println(getEndOfCurrentMonth());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String time  = sdf.format(getEndOfCurrentMonth());
        System.out.println(time);
        boolean isFirday = isFriday(today);
        System.out.println(isFirday);*/
//        System.out.println(getWorkDay(d1));
//        System.out.println(getWorkDay(d2));
//        System.out.println(getWorkDay(d3));
    }

    public static List<String> getBetweenDate(String startTime, String endTime){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime()<=endDate.getTime()){
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.DATE, 1);
                // 获取增加后的日期
                startDate=calendar.getTime();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 获取出生到现在多少天
     *
     * @param date  当前日期
     * @param date1 生日
     * @return
     */
    public static int birthdayDay(Date date, Date date1) {
        long betweenDays = (date.getTime() - date1.getTime()) / (1000L*3600L*24L);
        return (int) Math.abs(betweenDays);
    }
    /**
     * 添加天数
     * @param date
     * @param day
     * @return  添加后的时间
     */
    public static  Date addDay(Date date ,int day){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        // 把日期往后增加一天,整数  往后推,负数往前移动
        calendar.add(Calendar.DATE, day);
        // 这个时间就是日期往后推一天的结果
        return  calendar.getTime();
    }
    /**
     * 将字符串日期格式化为日期对象。
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToDateMilisV2(String formatDate) {
        Date date  = parseToDate(formatDate);
        formatDate = formatDayToStr(date);
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (formatDate.contains("年") || formatDate.contains("月") || formatDate.contains("日")) {
                sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
                formatDate += " 23时59分59秒";
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            if (formatDate.contains("/")) {
                sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");
                formatDate += " 23/59/59";
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            formatDate += " 23:59:59";
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException("800000", "日期格式错误");
        }
    }
}
